<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>Document</title>
    <style>
        
    </style>
</head>
<body>
    <table border="1" width="500" align="center">
        <thead>
            <tr>
                <th>选中</th>
                <th>名称</th>
                <th>价格</th>
                <th>数量</th>
                <th>小计</th>
                <th>操作</th>
            </tr>
        </thead>
        <tbody>
        </tbody>
        <tfoot>
            <tr>
                <td colspan="2"><input type="checkbox" id="allCheck"><label for="allCheck">全选</label></td>
                <td colspan="2">总数量：<span id="allNum">0</span></td>
                <td>总价：<span id="allPrice">0</span></td>
                <td id="allDel">批量删除</td>
            </tr>
        </tfoot>
    </table>
</body>
<script>

    const data = [{
        proName:"手机",
        price:2999,
        num:3,
        proId:"235235",
        flag:true
    },{
        proName:"电脑",
        price:3999,
        num:2,
        proId:"asgdfg",
        flag:true
    },{
        proName:"冰箱",
        price:1999,
        num:5,
        proId:"765q7w864e",
        flag:false
    },{
        proName:"洗衣机",
        price:999,
        num:1,
        proId:"65aesgrjh",
        flag:true
    }];

    // 1. 获取数据，获取元素
    // 2. 渲染结构
    
    // 3. 绑定事件
    // 4. 单选影响全选
    // 5. 全选影响单选
    // 6. 修改数量同步小计，总数量，总价
    // 7. 删除商品同步总数量，总价
    // 8. 批量删除，删除选中的商品

    class Cart{
        constructor(){
            // 1. 获取数据
            this.data = data;
            // 2. 获取元素
            this.tbody = document.querySelector("tbody");
            this.allCheck = document.querySelector("#allCheck");
            this.allNum = document.querySelector("#allNum");
            this.allPrice = document.querySelector("#allPrice");
            this.allDel = document.querySelector("#allDel");
            // 3. 渲染页面结构
            this.render();
            // 4. 绑定事件
            this.addEvent();
            // 5. 设置或计算默认
            this.init();
        }
        init(){
            // 判断全选
            this.allCheck.checked = this.data.every(val=>val.flag)
            // 计算总数
            this.allNum.innerHTML = this.data.reduce((prev,val)=>prev + val.num, 0);
            // 计算总价
            this.allPrice.innerHTML = this.data.reduce((prev,val)=>prev + (val.num * val.price), 0);
        }
        render(){
            let str = "";
            this.data.forEach(val=>{
                str += `<tr myid="${val.proId}">
                    <td><input type="checkbox" ${val.flag ? 'checked' : ''} class="check"></td>
                    <td>${val.proName}</td>
                    <td class="price">${val.price}</td>
                    <td><input type="number" value="${val.num}" class="num"></td>
                    <td class="subTotal">${ val.num * val.price }</td>
                    <td class="del">删除</td>
                </tr>`
            })
            this.tbody.innerHTML = str;
        }
        addEvent(){
            const that = this;
            this.tbody.addEventListener("change", proxy("check", function(){
                // 获取当前正在操作的商品的id
                that.id = this.parentNode.parentNode.getAttribute("myid");
                // 5. 修改选中状态后，更新数据
                that.setData(i=>{
                    // 修改数据中的选中状态
                    that.data[i].flag = this.checked;
                    // 6. 根据数据中的单个商品的选中状态，计算全选是否应该被选中
                    that.allCheck.checked = that.data.every(val=>val.flag)
                });
            }));
            this.tbody.addEventListener("input", proxy("num", function(){
                // 获取当前商品元素的父级
                const tr = this.parentNode.parentNode;
                // 获取当前商品的单价
                const price = tr.querySelector(".price").innerHTML;
                // 获取当前正在操作的商品的id
                that.id = tr.getAttribute("myid");

                // 将小计元素的内容设置为：数量 * 单价
                tr.querySelector(".subTotal").innerHTML = this.value * price;
                
                // 7. 修改数量之后，更新数据
                that.setData(i=>{
                    // 修改数据中的数量
                    that.data[i].num = this.value-0;
                    // 8. 根据数据中的单个商品的数量，计算总数量
                    that.allNum.innerHTML = that.data.reduce((prev,val)=>prev + val.num, 0);
                    // 9. 根据数据中的单个商品的数量，计算总价
                    that.allPrice.innerHTML = that.data.reduce((prev,val)=>prev + (val.num * val.price), 0);
                });
            }));
            this.tbody.addEventListener("click", proxy("del", function(){
                // 获取当前正在操作的商品的id
                that.id = this.parentNode.getAttribute("myid");
                // 删除DOM
                this.parentNode.remove();
                // 10. 删除之后，更新数据
                that.setData(i=>{
                    that.data.splice(i, 1);

                    // 根据数据中的单个商品的数量，计算总数量
                    that.allNum.innerHTML = that.data.reduce((prev,val)=>prev + val.num, 0);
                    // 根据数据中的单个商品的数量，计算总价
                    that.allPrice.innerHTML = that.data.reduce((prev,val)=>prev + (val.num * val.price), 0);
                })
            }))
            // 11. 给全选绑定事件
            this.allCheck.onchange = function(){
                // 修改DOM：所有复选项状态同步
                const checks = document.querySelectorAll(".check");
                [...checks].forEach(val=>{
                    val.checked = this.checked;
                });
                // 修改数据
                that.data.forEach(val=>{
                    val.flag = this.checked;
                })
            }
            // 12. 给批量删除绑定事件
            this.allDel.onclick = function(){
                // 更新数据：剔除flag为true的数据
                that.data = that.data.filter(val=>!val.flag)
                // 更新DOM
                // that.render();
                // 删除指定DOM
                const trs = that.tbody.children;
                [...trs].forEach(val=>{
                    if(val.querySelector(".check").checked){
                        val.remove();
                    }
                })

                that.allCheck.checked = false;
                // 根据数据中的单个商品的数量，计算总数量
                that.allNum.innerHTML = that.data.reduce((prev,val)=>prev + val.num, 0);
                    // 根据数据中的单个商品的数量，计算总价
                that.allPrice.innerHTML = that.data.reduce((prev,val)=>prev + (val.num * val.price), 0);
            }
        }
        setData(cb){
            // 根据当前正在操作的商品的id，从总数据中查找到相同数据的索引
            let i = 0;
            this.data.some((val,idx)=>{
                i = idx;
                return val.proId === this.id
            })
            // 执行外部传入的操作
            cb(i);
        }
    }
    new Cart;


    function proxy(select, cb){
        return function(eve){
            const e = eve || window.event;
            const target = e.srcElement || e.target;
            if(target.className === select){
                cb.call(target);
            }
        }
    }






    // setData2(){
    //     // 根据当前正在操作的商品的id，从总数据中查找到相同数据，修改数量
    //     this.data.some(val=>{
    //         if(val.proId === this.id){
    //             val.num = this.val-0;
    //             return true;
    //         }
    //     })
    //     // 根据数据中的单个商品的数量，计算总数量
    //     this.allNum.innerHTML = this.data.reduce((prev,val)=>prev + val.num, 0);
        
    //     // 根据数据中的单个商品的数量，计算总价
    //     this.allPrice.innerHTML = this.data.reduce((prev,val)=>prev + (val.num * val.price), 0);
    // }
    // setData(){
    //     // 根据当前正在操作的商品的id，从总数据中查找到相同数据，修改选中状态
    //     this.data.some(val=>{
    //         if(val.proId === this.id){
    //             val.flag = this.checked;
    //             return true;
    //         }
    //     })
    //     // 根据数据中的单个商品的选中状态，计算全选是否应该被选中
    //     this.allCheck.checked = this.data.every(val=>val.flag)
    // }

    
</script>
</html>